// MP3Tag.cpp: implementation of the CMP3Tag class.
//
//////////////////////////////////////////////////////////////////////

#include "MP3Tag.h"

#include <f32file.h>
#include <UTF.H>
#include <EIKENV.H>		 // For envir
#include <charconv.h> 	 // CCnvCharacterSetConverter
#include <string.h>

_LIT8(TAGFLAG, "TAG");
_LIT(Name_Title, "Title");
_LIT(Name_Artist, "Artist");
_LIT(Name_Album, "Album");
_LIT(Name_Year, "Year");
_LIT(Name_Comment, "Comment");
_LIT(Name_Genre, "Genre");


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CMP3Tag::CMP3Tag()
{

}

CMP3Tag::~CMP3Tag()
{
}

TInt CMP3Tag::GetTagInfo(TInt aIndex, TDes& aName, TDes& aValue)
{
	switch (aIndex) 
	{
	case 0:		// Title
		aName = Name_Title;
		aValue = iTitle;
		break;
	case 1:		// Artist
		aName = Name_Artist;
		aValue = iArtist;
		break;
	case 2:		// Album
		aName = Name_Album;
		aValue = iAlbum;
		break;
	case 3:		// Year
		aName = Name_Year;
		aValue = iYear;
		break;
	case 4:		// Comment
		aName = Name_Comment;
		aValue = iComment;
		break;
	case 5:		// Genre
		aName = Name_Genre;
		aValue = iGenre;
		break;
	default:
		return 1;
	}
	
	return 0;
}

TInt CMP3Tag::GetTagCount()
{
	return TAGID3V1_COUNT;
}

TInt CMP3Tag::_GetPosByIndex(const TDesC& aName)
{
	TInt nPos;

	if (aName == Name_Title)		// Title
		nPos = 3;
	else if (aName == Name_Artist)	// Artist
		nPos = 3 + 30;
	else if (aName == Name_Album)	// Album
		nPos = 3 + 30 + 30;
	else if (aName == Name_Year)	// Year
		nPos = 3 + 30 + 30 + 30;
	else if (aName == Name_Comment)	// Comment
		nPos = 3 + 30 + 30 + 30 + 4;
	else if (aName == Name_Genre)	// Genre
		nPos = 3 + 30 + 30 + 30 + 4 + 30;
	else
		nPos = 0;

	return nPos;
}

TInt CMP3Tag::ChangeTagL(RFs& aSession, const CDesCArray& aTagNames, const CDesCArray& aTagValues)
{
	RFile file;
	TInt nPos2, result;
	
	User::LeaveIfError(file.Open(aSession, iFilePath, EFileShareAny|EFileWrite));
	
	CCnvCharacterSetConverter* converter=CCnvCharacterSetConverter::NewLC();
	
	// Check if there is conversion between GBK/GB2312 and unicode 
	// if(converter->PrepareToConvertToOrFromL(KCharacterSetIdentifierGb2312,
	if (converter->PrepareToConvertToOrFromL(KCharacterSetIdentifierGbk,
		CEikonEnv::Static()->FsSession()) != CCnvCharacterSetConverter::EAvailable)
	{
		result = ERR_TEXTENCODE;
	}
	else
	{
		// Convert and store the ID3 information
		TInt state=CCnvCharacterSetConverter::KStateDefault;
		TBuf8<TAGID3V1_MAXLEN> value;

		// Individual tag size
		TInt TagSize[] = {30, 30, 30, 4, 30, 1};
			
		for (int i=0; i<aTagNames.Count(); i++)
		{
			if (aTagValues[i] != KUnchangeFlag)	// Need to change
			{
				// Seek to the last 128 byte, for read the tag3 v1 information
				TInt nPos = _GetPosByIndex(aTagNames[i]);
				nPos2 = -TAGID3V1_LENGTH; 
					
				User::LeaveIfError(file.Seek(ESeekEnd, nPos2));
				User::LeaveIfError(file.Seek(ESeekCurrent, nPos));

				// Erase old information, use the unconvert buffer to fill
				value.FillZ(TAGID3V1_MAXLEN);
				file.Write(value, TagSize[i]);

				// Convert chars
				if (CCnvCharacterSetConverter::EErrorIllFormedInput 
					== converter->ConvertFromUnicode(value, aTagValues[i], state))
				{
					value = KEmtpy8;
				}
				
				// Seek back to write the real content
				//nPos = _GetPosByIndex(aTagNames[i]);
				//nPos2 = -TAGID3V1_LENGTH;
				nPos = -TagSize[i];
				//User::LeaveIfError(file.Seek(ESeekEnd, nPos2));
				User::LeaveIfError(file.Seek(ESeekCurrent, nPos));
			
				const TUint8* cStr = value.PtrZ();
				file.Write(value, strlen((char*)cStr));
				//file.Flush();
			}
		}
	}
	
	file.Close();
	CleanupStack::PopAndDestroy();
	
	return 0;
}

void CMP3Tag::ConstructL(RFs& aSession, TFileName& aFile)
{
	MMediaTag::ConstructL(aSession, aFile);
	
	RFile file;

	User::LeaveIfError(file.Open(aSession, aFile, EFileShareAny|EFileRead));
	
	// Seek to the last 128 byte, for read the tag3 v1 information
	TInt nPos = -TAGID3V1_LENGTH; 
	User::LeaveIfError(file.Seek(ESeekEnd, nPos));
	
	TBuf8<128> tagbuf;
	User::LeaveIfError(file.Read(tagbuf));
	
	file.Close();
	
	// Assgin tag
	TAG3V1_INFO* TagInfo = (TAG3V1_INFO*)tagbuf.Ptr();	
	
	TInt result;

	CCnvCharacterSetConverter* converter = CCnvCharacterSetConverter::NewLC();
	// Check if there is conversion between GBK/GB2312 and unicode 
	// if(converter->PrepareToConvertToOrFromL(KCharacterSetIdentifierGb2312,
	
	if (converter->PrepareToConvertToOrFromL(KCharacterSetIdentifierGbk,
		CEikonEnv::Static()->FsSession()) != CCnvCharacterSetConverter::EAvailable)
	{
		result = ERR_TEXTENCODE;
	}
	else
	{
		// Convert and store the ID3 information
		TInt state=CCnvCharacterSetConverter::KStateDefault;
		TBuf8<TAGID3V1_MAXLEN> text;
		
		// Convert Artist section
		text.FillZ(TAGID3V1_MAXLEN);
		text.Copy((const TUint8*)TagInfo->iArtist, sizeof(TagInfo->iArtist));
				
		if (CCnvCharacterSetConverter::EErrorIllFormedInput 
			== converter->ConvertToUnicode(iArtist, text, state))
		{
			iArtist = KEmtpy;
		}

		// Album
		text.FillZ(TAGID3V1_MAXLEN);
		text.Copy((const TUint8*)TagInfo->iAlbum, sizeof(TagInfo->iAlbum));
		//TUint8* pPtr = (TUint8 *)text.Ptr();
		//pPtr[strlen(TagInfo->iAlbum)] = 0;
		
		if (CCnvCharacterSetConverter::EErrorIllFormedInput 
			== converter->ConvertToUnicode(iAlbum, text, state))
		{
			iAlbum = KEmtpy;
		}

		// Year
		text.FillZ(TAGID3V1_MAXLEN);
		text.Copy((const TUint8*)TagInfo->iYear, sizeof(TagInfo->iYear));
		
		if (CCnvCharacterSetConverter::EErrorIllFormedInput 
			== converter->ConvertToUnicode(iYear, text, state))
		{
			iYear = KEmtpy;
		}

		// Comment
		text.FillZ(TAGID3V1_MAXLEN);
		text.Copy((const TUint8*)TagInfo->iComment, sizeof(TagInfo->iComment));
		
		if (CCnvCharacterSetConverter::EErrorIllFormedInput 
			== converter->ConvertToUnicode(iComment, text, state))
		{
			iComment = KEmtpy;
		}

		// Title
		text.FillZ(TAGID3V1_MAXLEN);
		text.Copy((const TUint8*)TagInfo->iTitle, sizeof(TagInfo->iTitle));
		
		if (CCnvCharacterSetConverter::EErrorIllFormedInput 
			== converter->ConvertToUnicode(iTitle, text, state))
		{
			iTitle = KEmtpy;
		}

		// Genre
		text.FillZ(TAGID3V1_MAXLEN);
		text.Copy((const TUint8*)TagInfo->iGenre, sizeof(TagInfo->iGenre));
		
		if (CCnvCharacterSetConverter::EErrorIllFormedInput 
			== converter->ConvertToUnicode(iGenre, text, state))
		{
			iGenre = KEmtpy;
		}

		result = ERR_NOERROR;
	}

	CleanupStack::PopAndDestroy();
}

void CMP3Tag::_PrintTags()
{
	// Debug
	TBuf<TAGID3V1_MAXLEN> name;
	TBuf<TAGID3V1_MAXLEN> value;
	_LIT(aFmt, "%s - %s\n");

	for (int i=0; i<TAGID3V1_COUNT; i++)
	{
		GetTagInfo(i, name, value);
		//RDebug::Print(aFmt, name, value);
		RDebug::Print(name);
		RDebug::Print(value);
	}
}